﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Cos.Core.Interception
{
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.InterceptionExtension;

    public class InterceptOnRegisterContainerExtension : UnityContainerExtension
    {
        protected override void Initialize()
        {
            Container.AddNewExtension<Interception>();

            Context.Registering += (sender, e) => this.SetInterceptorFor(e.TypeFrom);

            Context.RegisteringInstance += (sender, e) => this.SetInterceptorFor(e.RegisteredType);
        }

        private void SetInterceptorFor(Type typeToIntercept)
        {
            var interceptor = this.SelectInterceptorFor(typeToIntercept);

            if (interceptor != null)
            {
                var instanceInterceptor = interceptor as IInstanceInterceptor;

                if (instanceInterceptor != null)
                {
                    Container.Configure<Interception>().SetInterceptorFor(typeToIntercept, instanceInterceptor);
                }
                else
                {
                    Container.Configure<Interception>().SetInterceptorFor(typeToIntercept, interceptor as ITypeInterceptor);
                }
            }
        }

        private IInterceptor SelectInterceptorFor(Type typeToIntercept)
        {
            if (typeToIntercept == null)
            {
                return null;
            }

            if (typeToIntercept.IsMarshalByRef)
            {
                return new TransparentProxyInterceptor();
            }

            if (typeToIntercept.IsInterface)
            {
                return new TransparentProxyInterceptor();
            }

            if (typeToIntercept.IsClass)
            {
                return new VirtualMethodInterceptor();
            }

            return null;
        }
    }
}
